#ifndef _BUFFER_HPP_
#error "This file must be included only from Buffer.h"
#endif


#include <memory.h>
#include <stdexcept> 
#include <cassert>

namespace sd
{
namespace tools
{
namespace buffer
{


inline void Buffer::resize( size_t newSize )
{
	if ( newSize > reserv_ )
		realloc( newSize );
	size_ = newSize;
}


inline void Buffer::source( const Buffer& ref )
{
	resize( ref.size() );
	memcpy( (char*)ptr_, ref.ptr_, ref.size() );			
}

inline void Buffer::add( const Buffer& ref )
{
	size_t oldSize = size();
	resize( ref.size() + oldSize );
	memcpy( (char*)ptr_ + oldSize, ref.ptr_, ref.size() );
}


template< typename T >
T& Buffer::cast( size_t index )
{
	assert( sizeof( T ) * index < size_ );
	return ((T*)ptr_)[index];		 
}


template< typename T >
const T& Buffer::cast( size_t index )const
{
	assert( sizeof( T ) * index < size_ );
	return ((T*)ptr_)[index];		 
}


inline Buffer& Buffer::operator+=( const Buffer& ref )
{
	add( ref );
	return *this;
}

inline Buffer& Buffer::operator=( const Buffer& ref )
{
	source( ref );
	return *this;
}

inline bool Buffer::operator==( const Buffer& ref )const
{
	if ( ref.size() != size() )
		return false;
	return memcmp( begin(), ref.begin(), size() )==0;
}


template< int BufferSize, typename T >
void StaticBuffer< BufferSize, T >::realloc( size_t s )
{
	if ( s > BufferSize )
		throw std::logic_error("Maximum size in StaticBuffer");
	else
		if ( size() > s )
			size_ = s;
}



inline void DynamicBuffer::realloc( size_t newAllocSize )
{
	char* newValue = new char[newAllocSize];
	reserv_ = newAllocSize;
	if ( size() > newAllocSize )
		size_ = newAllocSize;
	if( size() )
		memcmp( newValue, begin(), size() );
	delete[] ptr_;
	ptr_ = newValue;
}



inline void PtrBuffer::reset( const Buffer& ref )
{
	ptr_ = ref.begin();
	size_ = ref.size();
	reserv_ = ref.size();
}


inline void PtrBuffer::realloc( size_t s )
{
	if ( s > reserv_ )
		throw std::logic_error("Can not change reserv in PtrBuffer");
	else
		if ( size_ > s )
			size_ = s;
}





}//namespace buffer
}//namespace tools
}//namespace sd